home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The CICA Windows Explosion!
/
The CICA Windows Explosion! - Disc 2.iso
/
programr
/
upc12bs1.zip
/
LIB
/
hostable.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-06-21
|
28KB
|
701 lines
/*--------------------------------------------------------------------*/
/* h o s t a b l e . c */
/* */
/* Remote host table routines for UUPC/extended */
/*--------------------------------------------------------------------*/
/*--------------------------------------------------------------------*/
/* Changes Copyright (c) 1990-1993 by Kendra Electronic */
/* Wonderworks. */
/* */
/* All rights reserved except those explicitly granted by the */
/* UUPC/extended license agreement. */
/*--------------------------------------------------------------------*/
/*--------------------------------------------------------------------*/
/* RCS Information */
/*--------------------------------------------------------------------*/
/*
* $Id: hostable.c 1.7 1993/06/21 02:17:31 ahd Exp $
*
* $Log: hostable.c $
* Revision 1.7 1993/06/21 02:17:31 ahd
* Correct errors in mail routing via HOSTPATH
*
* Revision 1.6 1993/05/29 15:19:59 ahd
* Allow configured systems, passwd files
*
* Revision 1.5 1993/04/11 00:32:29 ahd
* Global edits for year, TEXT, etc.
*
* Revision 1.4 1993/04/04 04:57:01 ahd
* Trap existence of local host name in SYSTEMS file
*
* Revision 1.3 1992/12/18 12:05:57 ahd
* Suppress duplicate machine state messages to improving OS/2 scrolling
*
* Revision 1.3 1992/12/18 12:05:57 ahd
* Suppress duplicate machine state messages to improving OS/2 scrolling
*
* Revision 1.2 1992/11/22 20:58:55 ahd
* Use strpool to allocate const strings
*
* 18 Mar 1990 Create hostable.c from router.c ahd
* Move code to generate localdomain to here ahd
* 22 Apr 90 Perform check for full host name before examining
* name without domain. ahd
* 29 Jul 90 Only load host table based on first six characters
* of host name. ahd
*
*/
#include <ctype.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include "lib.h"
#include "hlib.h"
#include "hostable.h"
#include "security.h"
currentfile();
static struct HostTable *hosts = NULL;
static size_t HostElements = 0;
static size_t loadhost( void );
static int hostcmp( const void *a , const void *b );
static size_t localdomainl; /* Length of localdomain */
/*--------------------------------------------------------------------*/
/* c h e c k n a m e */
/* */
/* Perform a search for a single host name */
/* */
/* Rewritten for release 1.10a. The old release had */
/* most of the same logic, but nested it inside the search */
/* loop; adding new cases (specifically, the wildcard domain */
/* search) was difficult. This version is slower because it */
/* makes multiple passes through the host table, but this */
/* isn't really performance code for a small (under 100 hosts) */
/* table. ahd 26 April 1991 */
/* */
/* Note because we save the arguments and use a static variable */
/* to save the result of searches, this function is not */
/* recursive! */
/*--------------------------------------------------------------------*/
struct HostTable *checkname(const char *name)
{
char hostname[MAXADDR]; /* Local copy of name to process */
char *period; /* Pointer "." in hostname */
size_t namel; /* Length of the name input */
size_t column; /* Length of the name input */
static char savename[MAXADDR] = "";
/* Saved copy of name to make function
reducible */
static struct HostTable *hostz;
/*--------------------------------------------------------------------*/
/* Validate the argument */
/*--------------------------------------------------------------------*/
if ((name == NULL) || ((namel = strlen(name)) == 0))
{
printmsg(0,"checkname: Invalid (missing) hostname passed");
panic();
return NULL; /* Never executed */
}
/*--------------------------------------------------------------------*/
/* If same argument as last time, return same result; otherwise */
/* save input for next pass */
/*--------------------------------------------------------------------*/
if (equali(name, savename))
return hostz;
strcpy( savename, name); /* Save for next pass */
/*--------------------------------------------------------------------*/
/* Search for the full name */
/*--------------------------------------------------------------------*/
if ((hostz = searchname(name, MAXADDR)) != BADHOST)
return hostz;
/*--------------------------------------------------------------------*/
/* If the name already has the local domain attached, search for */
/* the host name without the domain. */
/*--------------------------------------------------------------------*/
column = namel - localdomainl;
if ((namel > localdomainl) && equali(E_localdomain, &name[column]) &&
(name[ column - 1] == '.'))
{
if ((hostz = searchname(name,column-1 )) != BADHOST)
return hostz;
} /* if */
/*--------------------------------------------------------------------*/
/* If the name already has the UUCP domain attached, search for */
/* the host name without the domain. */
/*--------------------------------------------------------------------*/
column = namel - 5;
if ((column > 0) && equali(".UUCP", &name[column]))
{
if ((hostz = searchname(name, column )) != BADHOST)
return hostz;
} /* if */
/*--------------------------------------------------------------------*/
/* Search for the name in the local domain */
/*--------------------------------------------------------------------*/
if ((namel + localdomainl + 2) < MAXADDR)
{
sprintf(hostname,"%s.%s",name,E_localdomain);
if ((hostz = searchname(hostname, MAXADDR)) != BADHOST)
return hostz;
} /* if */
/*--------------------------------------------------------------------*/
/* If a simple name and not found, return search for truncated */
/* UNIX name. */
/*--------------------------------------------------------------------*/
if ( strchr(name,'.') == NULL )
return checkreal( name );
/*--------------------------------------------------------------------*/
/* Perform a wildcard domain name search */
/*--------------------------------------------------------------------*/
period = (char *) name; /* Begin at front of name */
while( period != NULL )
{
sprintf( hostname,(*period == '.') ? "*%s" : "*.%s",period);
/* We add the missing period for the
first pass through the loop */
if ((hostz = searchname(hostname, MAXADDR)) != BADHOST)
return hostz;
period = strchr(++period,'.'); /* Not found, search for next
higher domain */
}
/*--------------------------------------------------------------------*/
/* We didn't find the host. Return failure to caller */
/*--------------------------------------------------------------------*/
return BADHOST;
} /* checkname */
/*--------------------------------------------------------------------*/
/* c h e c k r e a l */
/* */
/* Perform a search for a real (connected) simple host name */
/*--------------------------------------------------------------------*/
struct HostTable *checkreal(const char *name)
{
size_t namel = max( strlen(name), HOSTLEN);
struct HostTable *hostp = searchname( name, namel );
/*--------------------------------------------------------------------*/
/* If we didn't find the host, return failure */
/*--------------------------------------------------------------------*/
if ((hostp == BADHOST) || (hostp->hstatus >= nocall))
return hostp; /* Return raw information */
else
return BADHOST; /* Not a real host, invalid for our
purposes */
} /* searchreal */
/*--------------------------------------------------------------------*/
/* s e a r c h n a m e */
/* */
/* Look up a system name in our systems (L.sys) file. */
/* Only the first 7 characters of a system name is significant. */
/*--------------------------------------------------------------------*/
struct HostTable *searchname(const char *name, const size_t namel)
{
int lower;
int upper;
/*------------------------------------------------------------------*/
/* Initialize the host name table if needed */
/*------------------------------------------------------------------*/
if (HostElements == 0) /* host table initialized yet? */
HostElements = loadhost(); /* No --> load it */
lower = 0;
upper = HostElements - 1;
while ( lower <= upper )
{
int midpoint = (lower + upper) / 2;
int hit;
/*--------------------------------------------------------------------*/
/* Compare for up to the specified length of the host name, but */
/* never less than the length of the item we are comparing it */
/* to. In other words, the search key can be shorter than the */
/* table entry for a simple host name. */
/* */
/* This mostly affects simple host names, as domain names */
/* have a Very Large Number (VLN) passed into to insure we */
/* compare the entire length of the name. */
/*--------------------------------------------------------------------*/
hit = strnicmp(name,hosts[midpoint].hostname,namel);
if (hit > 0)
lower = midpoint + 1;
else if ((hit < 0) || (strlen(hosts[midpoint].hostname) > namel))
upper = midpoint - 1;
else {
printmsg(8,"searchname: Looking for \"%s\" of length %d,\
found \"%s\"",
name, namel, hosts[midpoint].hostname);
return &hosts[midpoint];
}
}
/*--------------------------------------------------------------------*/
/* We didn't find the host. Return failure to caller */
/*--------------------------------------------------------------------*/
printmsg(8,"searchname: Looking for \"%s\", did not find it",
name);
return BADHOST;
} /* searchname */
/*--------------------------------------------------------------------*/
/* n e x t h o s t */
/* */
/* Returns next host in table with requested attribute */
/*--------------------------------------------------------------------*/
struct HostTable *nexthost( const boolean start )
{
static size_t current = 0;
if (HostElements == 0) /* host table initialized yet? */
HostElements = loadhost(); /* No --> load it */
if (start)
current = 0;
else
current ++;
while ( current < HostElements )
{
if (hosts[current].hstatus >= nocall)
return &hosts[current];
else
current++;
}
return BADHOST;
} /* nexthost */
/*--------------------------------------------------------------------*/
/* i n i t h o s t */
/* */
/* Intializes a host table entry for for loadhost */
/*--------------------------------------------------------------------*/
struct HostTable *inithost(char *name)
{
size_t hit = HostElements;
size_t element = 0;
static size_t max_elements = 32; /* This is automatically
raised if we run out of room */
if (hosts == NULL)
{
hosts = calloc(max_elements, sizeof(*hosts));
printmsg(5,"inithost: Allocated room for %d host entries",
max_elements);
}
else if ( max_elements == HostElements )
{
max_elements = max_elements * 2;
hosts = realloc(hosts , max_elements * sizeof(*hosts));
printmsg(5,"inithost: reallocated room for %d host entries",
max_elements);
}
checkref(hosts);
/*--------------------------------------------------------------------*/
/* Add the host to the table. Note that we must add the host */
/* to the table ourselves (rather than use lsearch) because we */
/* must make a copy of the string; the *token we use for the */
/* search is in the middle of our I/O buffer! */
/*--------------------------------------------------------------------*/
while ( element < hit )
{
if (equali( hosts[element].hostname , name ))
hit = element;
else
element++;
}
/*--------------------------------------------------------------------*/
/* If a new element, initialize the block */
/*--------------------------------------------------------------------*/
if (hit == HostElements)
{
memset( &hosts[hit] , 0, sizeof hosts[hit] );
hosts[hit].hostname = newstr(name);
checkref( hosts[hit].hostname );
hosts[hit].anylogin = TRUE; /* Allow generic login by default */
HostElements ++ ;
} /* if */
return &hosts[hit];
} /* inithost */
/*--------------------------------------------------------------------*/
/* l o a d h o s t */
/* */
/* Initializes table of known host names for checkname */
/*--------------------------------------------------------------------*/
static size_t loadhost()
{
FILE *ff;
char buf[BUFSIZ];
char *token;
char s_hostable[FILENAME_MAX]; /* full-name of hostable file */
size_t hit;
struct HostTable *hostp;
/*--------------------------------------------------------------------*/
/* Validate the domain name */
/*--------------------------------------------------------------------*/
token = strrchr(E_domain,'.');
if (token == NULL)
{
printmsg(0,"Domain name \"%s\" is invalid, missing period",E_domain);
panic();
}
/*--------------------------------------------------------------------*/
/* Load the local host information */
/*--------------------------------------------------------------------*/
hostp = inithost(E_nodename);
hostp->hstatus = localhost;
hostp->realname = E_nodename; /* Don't let user alias our system
name */
/*--------------------------------------------------------------------*/
/* Now do the local domain information */
/*--------------------------------------------------------------------*/
hostp = inithost(E_domain);
if (hostp->via == NULL ) /* Not initialized? */
hostp->via = E_nodename; /* Correct --> Route via local */
else
panic(); /* "Houston, we a have problem" -
Apollo 13 */
hostp->realname = E_nodename;
/*--------------------------------------------------------------------*/
/* If we allow anonymous UUCP, load the dummy host we use for */
/* connections to such hosts */
/*--------------------------------------------------------------------*/
if ( E_anonymous != NULL )
{
hostp = inithost( ANONYMOUS_HOST );
hostp->hstatus = nocall;
hostp->via = E_nodename;
hostp->hstats = malloc( sizeof *(hostp->hstats) );
checkref( hostp->hstats );
memset( hostp->hstats, 0, sizeof *(hostp->hstats) );
} /* if */
/*--------------------------------------------------------------------*/
/* Load names from the systems file */
/*--------------------------------------------------------------------*/
ff = FOPEN(E_systems, "r",TEXT_MODE);
if (ff == NULL)
{
printerr(E_systems);
panic();
}
while (! feof(ff))
{
if (fgets(buf,BUFSIZ,ff) == NULL) /* Try to read a line */
break; /* Exit if end of file */
token = strtok(buf,WHITESPACE);
if (token == NULL) /* Any data? */
continue; /* No --> read another line */
if (token[0] == '#')
continue; /* Line is a comment; loop again */
if ( equali( token, E_nodename ))
{
printmsg(0,"Error: Local host %s must not be in SYSTEMS file",
E_nodename );
panic();
}
hostp = inithost(token);
if (hostp->hstatus == phantom)
{
hostp->hstatus = nocall;
hostp->hstats = malloc( sizeof *(hostp->hstats) );
checkref( hostp->hstats );
memset( hostp->hstats, 0, sizeof *(hostp->hstats) );
}
} /* while */
fclose(ff);
/*--------------------------------------------------------------------*/
/* Now the load the routing file, if any. */
/*--------------------------------------------------------------------*/
mkfilename(s_hostable, E_confdir, PATHS);
if ((ff = FOPEN(s_hostable, "r",TEXT_MODE)) != NULL)
{
while (! feof(ff))
{
boolean freeit = FALSE;
if (fgets(buf,BUFSIZ,ff) == NULL) /* Try to read a line */
break; /* Exit if end of file */
token = strtok(buf,WHITESPACE);
if (token == NULL) /* Any data? */
continue; /* No --> read another line */
if (*token == '#')
continue; /* Line is a comment; loop again */
hostp = inithost(token);
token = strtok(NULL,WHITESPACE);
if ( token == NULL )
{
printmsg(0,"loadhost: Missing path name for host \"%s\"",
hostp->hostname);
freeit = TRUE;
}
/*--------------------------------------------------------------------*/
/* Gate way */
/*--------------------------------------------------------------------*/
else if (equal(token,"|"))
{
token = strtok(NULL,"\n");
if (( hostp->via != NULL ) || ( token == NULL ))
freeit = TRUE;
else {
hostp->hstatus = gatewayed;
while(isspace( *token )) /* Drop leading white space only */
token++;
if (*token == '\0') /* Empty string? */
freeit = TRUE; /* Yes --> Flag for error */
else
hostp->via = token = newstr(token);
} /* else if */
if ( freeit )
printmsg(0,"loadhost: Invalid/duplicate gateway for \"%s\"",
hostp->hostname );
} /* else if */
/*--------------------------------------------------------------------*/
/* Alias */
/*--------------------------------------------------------------------*/
else if (equal(token,"="))
{
token = strtok(NULL,WHITESPACE);
if (( hostp->realname == NULL ) && (token != NULL))
hostp->realname = token = newstr( token );
else {
printmsg(0,"loadhost: Invalid/duplicate alias of \"%s\"",
hostp->hostname );
freeit = TRUE;
} /* else */
} /* else if (equal(token,"=")) */
/*--------------------------------------------------------------------*/
/* Routing entry */
/*--------------------------------------------------------------------*/
else {
if ( hostp->via == NULL )
hostp->via = token = newstr( token );
else {
printmsg(0,"loadhost: Invalid/duplicate route for \"%s\"",
hostp->hostname );
freeit = TRUE;
} /* else */
} /* else */
if ( ! freeit )
{
checkref( token );
if (*token == '*') /* Wildcard on right side? */
{
printmsg(0,
"loadhost: Wildcard \"%s\" not allowed for real name of host \"%s\"",
token, hostp->hostname);
freeit = TRUE;
} /* if (*token == '*') */
} /* if ( ! freeit ) */
if ( freeit )
{
if ( hostp->hstatus == phantom )
HostElements--; /* Ignore the routing entry */
}
} /* end while */
fclose(ff);
}
else {
if ( debuglevel > 2 )
perror( s_hostable );
}
/*--------------------------------------------------------------------*/
/* Provide default for fromdomain */
/*--------------------------------------------------------------------*/
if (E_fdomain != NULL) /* If fromdomain provided ... */
{
hostp = inithost(E_fdomain);
if (hostp->via == NULL) /* Uninitialized? */
hostp->via = E_mailserv; /* Yes --> Use default route */
}
else
E_fdomain = E_domain; /* Use domain as fromdomain */
/*--------------------------------------------------------------------*/
/* Shrink the table to whatever we actually need, then sort it */
/*--------------------------------------------------------------------*/
hosts = realloc(hosts, HostElements * sizeof(*hosts));
checkref(hosts);
qsort(hosts, HostElements ,sizeof(hosts[0]) , hostcmp);
/*--------------------------------------------------------------------*/
/* If the user did not define a local domain, then generate one */
/* based on our own domain name; the generated name will either */
/* be of the format ".a.b.c" (incuding the trailing period) or */
/* a null string. */
/*--------------------------------------------------------------------*/
if ( E_localdomain == NULL )
{
E_localdomain = strchr(E_domain,'.');
if (E_localdomain == NULL)
E_localdomain = "UUCP";
else {
E_localdomain ++; /* Step past the period */
if ( !equali(E_localdomain, "UUCP" ) &&
(strchr( E_localdomain, '.' ) == NULL ))
/* Implied single level domain name? */
E_localdomain = E_domain;
/* Impossible, use both parts of name */
} /* else */
printmsg(3,"loadhost: local domain defined as \"%s\"",
E_localdomain);
} /* if */
localdomainl = strlen(E_localdomain);
/*--------------------------------------------------------------------*/
/* Amend for the sin of typing the domain wrong in the sample */
/* files for the old releases of UUPC/extended. */
/*--------------------------------------------------------------------*/
if (equali(E_localdomain,"UUPC"))
{
printmsg(0,"inithost: UUPC is an invalid domain name! "
"Change it to UUCP");
panic();
}
/*--------------------------------------------------------------------*/
/* Display the final table */
/*--------------------------------------------------------------------*/
for (hit = 0; hit < HostElements; hit++)
{
printmsg(8,"loadhost: entry[%02d] %-20s\tvia %s\talias %s",
hit,
hosts[hit].hostname,
(hosts[hit].via == NULL) ? "(self)" : hosts[hit].via,
(hosts[hit].realname == NULL)
? "(self)" : hosts[hit].realname);
} /* for */
/*--------------------------------------------------------------------*/
/* Return to caller */
/*--------------------------------------------------------------------*/
return (HostElements) ;
} /*loadhost*/
/*--------------------------------------------------------------------*/
/* h o s t c m p */
/* */
/* Accepts indirect pointers to two strings and compares */
/* them using stricmp (case insensitive string compare) */
/*--------------------------------------------------------------------*/
int hostcmp( const void *a , const void *b )
{
return stricmp(((struct HostTable*) a)->hostname,
((struct HostTable*) b)->hostname);
} /*hostcmp*/